package com.example.computer_exam_training_sys.service.impl;

import com.example.computer_exam_training_sys.dto.AchievementDTO;
import com.example.computer_exam_training_sys.entity.UserAchievement;
import com.example.computer_exam_training_sys.mapper.UserAchievementMapper;
import com.example.computer_exam_training_sys.service.UserAchievementService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.time.LocalDateTime;
import java.util.*;
import java.util.stream.Collectors;

@Service
public class UserAchievementServiceImpl implements UserAchievementService {

    @Autowired
    private UserAchievementMapper userAchievementMapper;

    @Override
    public List<AchievementDTO> getUserAchievements(Long userId) {
        List<UserAchievement> achievements = userAchievementMapper.findByUserId(userId);
        return achievements.stream()
                .map(this::convertToDTO)
                .collect(Collectors.toList());
    }

    @Override
    public List<UserAchievement> getUserAchievementsByType(Long userId, String achievementType) {
        return userAchievementMapper.findByUserIdAndType(userId, achievementType);
    }

    @Override
    @Transactional
    public void checkAchievements(Long userId, String activityType, Integer value) {
        // 根据活动类型和值检查是否解锁新成就
        List<UserAchievement> existingAchievements = userAchievementMapper.findByUserId(userId);
        Set<String> unlockedAchievements = new HashSet<>();
        for (UserAchievement achievement : existingAchievements) {
            unlockedAchievements.add(achievement.getAchievementName());
        }

        // 根据活动类型检查不同类型的成就
        switch (activityType) {
            case "practice":
                checkPracticeAchievements(userId, unlockedAchievements);
                break;
            case "exam":
                checkExamAchievements(userId, unlockedAchievements);
                break;
            case "learning":
                checkLearningAchievements(userId, unlockedAchievements);
                break;
            case "course":
                checkCourseAchievements(userId, unlockedAchievements);
                break;
            default:
                // 如果是直接传递的值，使用原来的逻辑
                if (shouldUnlockAchievement(activityType, value, unlockedAchievements)) {
                    UserAchievement newAchievement = createAchievement(userId, activityType, value);
                    userAchievementMapper.insert(newAchievement);
                }
        }
    }
    
    /**
     * 检查练习相关成就
     */
    private void checkPracticeAchievements(Long userId, Set<String> unlockedAchievements) {
        // 获取练习相关数据
        Integer practiceCount = userAchievementMapper.countPracticesByUserId(userId);
        Integer questionCount = userAchievementMapper.getTotalPracticeQuestionsByUserId(userId);
        Integer correctCount = userAchievementMapper.getTotalPracticeCorrectByUserId(userId);
        Integer practiceDays = userAchievementMapper.getDistinctPracticeDaysByUserId(userId);
        
        // 防止空值
        practiceCount = practiceCount != null ? practiceCount : 0;
        questionCount = questionCount != null ? questionCount : 0;
        correctCount = correctCount != null ? correctCount : 0;
        practiceDays = practiceDays != null ? practiceDays : 0;
        
        // 检查并解锁成就
        if (practiceCount >= 10 && !unlockedAchievements.contains("练习新手")) {
            unlockAchievement(userId, "practice", "练习新手", "完成10次练习");
        }
        
        if (practiceCount >= 50 && !unlockedAchievements.contains("练习达人")) {
            unlockAchievement(userId, "practice", "练习达人", "完成50次练习");
        }
        
        if (practiceCount >= 100 && !unlockedAchievements.contains("练习高手")) {
            unlockAchievement(userId, "practice", "练习高手", "完成100次练习");
        }
        
        if (questionCount >= 500 && !unlockedAchievements.contains("题海战术")) {
            unlockAchievement(userId, "practice", "题海战术", "完成500道练习题");
        }
        
        if (questionCount >= 1000 && !unlockedAchievements.contains("刷题王者")) {
            unlockAchievement(userId, "practice", "刷题王者", "完成1000道练习题");
        }
        
        // 计算正确率
        double correctRate = questionCount > 0 ? (double) correctCount / questionCount : 0;
        if (questionCount >= 100 && correctRate >= 0.9 && !unlockedAchievements.contains("精准答题")) {
            unlockAchievement(userId, "practice", "精准答题", "练习正确率达到90%");
        }
        
        if (practiceDays >= 7 && !unlockedAchievements.contains("坚持不懈")) {
            unlockAchievement(userId, "practice", "坚持不懈", "连续7天进行练习");
        }
    }
    
    /**
     * 检查考试相关成就
     */
    private void checkExamAchievements(Long userId, Set<String> unlockedAchievements) {
        // 获取考试相关数据
        Integer examCount = userAchievementMapper.countExamsByUserId(userId);
        Double averageScore = userAchievementMapper.getAverageExamScoreByUserId(userId);
        Integer passedExams = userAchievementMapper.countPassedExamsByUserId(userId);
        
        // 防止空值
        examCount = examCount != null ? examCount : 0;
        averageScore = averageScore != null ? averageScore : 0.0;
        passedExams = passedExams != null ? passedExams : 0;
        
        // 检查并解锁成就
        if (examCount >= 1 && !unlockedAchievements.contains("初次考试")) {
            unlockAchievement(userId, "exam", "初次考试", "完成第一次考试");
        }
        
        if (examCount >= 5 && !unlockedAchievements.contains("考试能手")) {
            unlockAchievement(userId, "exam", "考试能手", "完成5次考试");
        }
        
        if (examCount >= 20 && !unlockedAchievements.contains("考试达人")) {
            unlockAchievement(userId, "exam", "考试达人", "完成20次考试");
        }
        
        if (passedExams >= 10 && !unlockedAchievements.contains("及格专家")) {
            unlockAchievement(userId, "exam", "及格专家", "通过10次考试");
        }
        
        if (averageScore >= 90 && examCount >= 3 && !unlockedAchievements.contains("考霸")) {
            unlockAchievement(userId, "exam", "考霸", "考试平均分达到90分");
        }
    }
    
    /**
     * 检查学习时长相关成就
     */
    private void checkLearningAchievements(Long userId, Set<String> unlockedAchievements) {
        // 获取学习相关数据
        Integer totalStudyTime = userAchievementMapper.getTotalStudyTimeByUserId(userId);
        Integer distinctStudyDays = userAchievementMapper.getDistinctStudyDaysByUserId(userId);
        Integer studyDaysInLast30Days = userAchievementMapper.getStudyDaysInLast30DaysByUserId(userId);
        Integer maxConsecutiveDays = userAchievementMapper.getMaxConsecutiveStudyDaysByUserId(userId);
        
        // 防止空值
        totalStudyTime = totalStudyTime != null ? totalStudyTime : 0;
        distinctStudyDays = distinctStudyDays != null ? distinctStudyDays : 0;
        studyDaysInLast30Days = studyDaysInLast30Days != null ? studyDaysInLast30Days : 0;
        maxConsecutiveDays = maxConsecutiveDays != null ? maxConsecutiveDays : 0;
        
        // 学习时长按分钟计算
        int studyHours = totalStudyTime / 60;
        
        // 检查并解锁成就
        if (studyHours >= 10 && !unlockedAchievements.contains("初学者")) {
            unlockAchievement(userId, "learning", "初学者", "累计学习10小时");
        }
        
        if (studyHours >= 50 && !unlockedAchievements.contains("勤奋学习")) {
            unlockAchievement(userId, "learning", "勤奋学习", "累计学习50小时");
        }
        
        if (studyHours >= 100 && !unlockedAchievements.contains("学习专家")) {
            unlockAchievement(userId, "learning", "学习专家", "累计学习100小时");
        }
        
        if (distinctStudyDays >= 30 && !unlockedAchievements.contains("学习达人")) {
            unlockAchievement(userId, "learning", "学习达人", "累计学习30天");
        }
        
        if (maxConsecutiveDays >= 7 && !unlockedAchievements.contains("坚持一周")) {
            unlockAchievement(userId, "learning", "坚持一周", "连续学习7天");
        }
        
        if (maxConsecutiveDays >= 30 && !unlockedAchievements.contains("月度坚持")) {
            unlockAchievement(userId, "learning", "月度坚持", "连续学习30天");
        }
        
        if (studyDaysInLast30Days >= 25 && !unlockedAchievements.contains("专注学习")) {
            unlockAchievement(userId, "learning", "专注学习", "近30天内学习25天");
        }
    }
    
    /**
     * 检查课程完成相关成就
     */
    private void checkCourseAchievements(Long userId, Set<String> unlockedAchievements) {
        // 获取课程相关数据
        Integer completedCourses = userAchievementMapper.countCompletedCoursesByUserId(userId);
        Double maxCompletionRate = userAchievementMapper.getMaxCompletionRateByUserId(userId);
        
        // 防止空值
        completedCourses = completedCourses != null ? completedCourses : 0;
        maxCompletionRate = maxCompletionRate != null ? maxCompletionRate : 0.0;
        
        // 检查并解锁成就
        if (completedCourses >= 1 && !unlockedAchievements.contains("课程达人")) {
            unlockAchievement(userId, "course", "课程达人", "完成一门课程");
        }
        
        if (completedCourses >= 3 && !unlockedAchievements.contains("学有所成")) {
            unlockAchievement(userId, "course", "学有所成", "完成三门课程");
        }
        
        if (completedCourses >= 5 && !unlockedAchievements.contains("学霸")) {
            unlockAchievement(userId, "course", "学霸", "完成五门课程");
        }
        
        if (maxCompletionRate >= 50 && !unlockedAchievements.contains("半程学习")) {
            unlockAchievement(userId, "course", "半程学习", "课程完成率达到50%");
        }
        
        if (maxCompletionRate >= 100 && !unlockedAchievements.contains("完美学习")) {
            unlockAchievement(userId, "course", "完美学习", "课程完成率达到100%");
        }
    }
    
    /**
     * 解锁一个新成就
     */
    private void unlockAchievement(Long userId, String type, String name, String description) {
        UserAchievement achievement = new UserAchievement();
        achievement.setUserId(userId);
        achievement.setAchievementType(type);
        achievement.setAchievementName(name);
        achievement.setDescription(description);
        achievement.setEarnDate(LocalDateTime.now());
        userAchievementMapper.insert(achievement);
    }

    @Override
    public AchievementStatistics getAchievementStatistics(Long userId) {
        AchievementStatistics statistics = new AchievementStatistics();
        statistics.setTotalAchievements(userAchievementMapper.countByUserId(userId));
        statistics.setLearningAchievements(userAchievementMapper.countByUserIdAndType(userId, "learning"));
        statistics.setPracticeAchievements(userAchievementMapper.countByUserIdAndType(userId, "practice"));
        statistics.setExamAchievements(userAchievementMapper.countByUserIdAndType(userId, "exam"));
        statistics.setCourseAchievements(userAchievementMapper.countByUserIdAndType(userId, "course"));
        statistics.setRecentAchievements(userAchievementMapper.findLatestByUserId(userId, 5));
        return statistics;
    }

    @Override
    public List<UserAchievement> getLatestAchievements(Long userId, Integer limit) {
        return userAchievementMapper.findLatestByUserId(userId, limit);
    }

    @Override
    public List<AchievementSuggestion> getAchievementSuggestions(Long userId) {
        List<AchievementSuggestion> suggestions = new ArrayList<>();
        List<UserAchievement> existingAchievements = userAchievementMapper.findByUserId(userId);
        Set<String> unlockedAchievements = new HashSet<>();
        for (UserAchievement achievement : existingAchievements) {
            unlockedAchievements.add(achievement.getAchievementName());
        }

        // 获取用户当前的各项数据
        Integer practiceCount = userAchievementMapper.countPracticesByUserId(userId);
        Integer questionCount = userAchievementMapper.getTotalPracticeQuestionsByUserId(userId);
        Integer examCount = userAchievementMapper.countExamsByUserId(userId);
        Integer completedCourses = userAchievementMapper.countCompletedCoursesByUserId(userId);
        Integer distinctStudyDays = userAchievementMapper.getDistinctStudyDaysFromStatsByUserId(userId);
        Integer maxConsecutiveDays = userAchievementMapper.getMaxConsecutiveStudyDaysByUserId(userId);
        
        // 防止空值
        practiceCount = practiceCount != null ? practiceCount : 0;
        questionCount = questionCount != null ? questionCount : 0;
        examCount = examCount != null ? examCount : 0;
        completedCourses = completedCourses != null ? completedCourses : 0;
        distinctStudyDays = distinctStudyDays != null ? distinctStudyDays : 0;
        maxConsecutiveDays = maxConsecutiveDays != null ? maxConsecutiveDays : 0;

        // 添加未解锁的成就建议
        if (!unlockedAchievements.contains("学习达人")) {
            AchievementSuggestion suggestion = new AchievementSuggestion();
            suggestion.setAchievementType("learning");
            suggestion.setAchievementName("学习达人");
            suggestion.setDescription("累计学习30天");
            suggestion.setTargetValue(30);
            suggestion.setProgress(distinctStudyDays);
            suggestions.add(suggestion);
        }
        
        if (!unlockedAchievements.contains("月度坚持")) {
            AchievementSuggestion suggestion = new AchievementSuggestion();
            suggestion.setAchievementType("learning");
            suggestion.setAchievementName("月度坚持");
            suggestion.setDescription("连续学习30天");
            suggestion.setTargetValue(30);
            suggestion.setProgress(maxConsecutiveDays);
            suggestions.add(suggestion);
        }
        
        if (!unlockedAchievements.contains("练习高手")) {
            AchievementSuggestion suggestion = new AchievementSuggestion();
            suggestion.setAchievementType("practice");
            suggestion.setAchievementName("练习高手");
            suggestion.setDescription("完成100次练习");
            suggestion.setTargetValue(100);
            suggestion.setProgress(practiceCount);
            suggestions.add(suggestion);
        }
        
        if (!unlockedAchievements.contains("刷题王者")) {
            AchievementSuggestion suggestion = new AchievementSuggestion();
            suggestion.setAchievementType("practice");
            suggestion.setAchievementName("刷题王者");
            suggestion.setDescription("完成1000道练习题");
            suggestion.setTargetValue(1000);
            suggestion.setProgress(questionCount);
            suggestions.add(suggestion);
        }
        
        if (!unlockedAchievements.contains("考试能手")) {
            AchievementSuggestion suggestion = new AchievementSuggestion();
            suggestion.setAchievementType("exam");
            suggestion.setAchievementName("考试能手");
            suggestion.setDescription("完成5次考试");
            suggestion.setTargetValue(5);
            suggestion.setProgress(examCount);
            suggestions.add(suggestion);
        }
        
        if (!unlockedAchievements.contains("课程达人")) {
            AchievementSuggestion suggestion = new AchievementSuggestion();
            suggestion.setAchievementType("course");
            suggestion.setAchievementName("课程达人");
            suggestion.setDescription("完成一门课程");
            suggestion.setTargetValue(1);
            suggestion.setProgress(completedCourses);
            suggestions.add(suggestion);
        }

        return suggestions;
    }

    private boolean shouldUnlockAchievement(String activityType, Integer value, Set<String> unlockedAchievements) {
        // 根据活动类型和值判断是否应该解锁新成就
        switch (activityType) {
            case "learning":
                return value >= 30 && !unlockedAchievements.contains("学习达人");
            case "practice":
                return value >= 100 && !unlockedAchievements.contains("练习高手");
            case "exam":
                return value >= 5 && !unlockedAchievements.contains("考试能手");
            case "course":
                return value >= 1 && !unlockedAchievements.contains("课程达人");
            default:
                return false;
        }
    }

    private UserAchievement createAchievement(Long userId, String activityType, Integer value) {
        UserAchievement achievement = new UserAchievement();
        achievement.setUserId(userId);
        achievement.setAchievementType(activityType);
        
        // 设置成就名称和描述
        switch (activityType) {
            case "learning":
                achievement.setAchievementName("学习达人");
                achievement.setDescription("连续学习" + value + "天");
                break;
            case "practice":
                achievement.setAchievementName("练习高手");
                achievement.setDescription("完成" + value + "道练习题");
                break;
            case "exam":
                achievement.setAchievementName("考试能手");
                achievement.setDescription("完成" + value + "次考试");
                break;
            case "course":
                achievement.setAchievementName("课程达人");
                achievement.setDescription("完成一门课程");
                break;
        }
        
        achievement.setEarnDate(LocalDateTime.now());
        return achievement;
    }

    private AchievementDTO convertToDTO(UserAchievement achievement) {
        AchievementDTO dto = new AchievementDTO();
        dto.setAchievementId(achievement.getAchievementId());
        dto.setUserId(achievement.getUserId());
        dto.setAchievementType(achievement.getAchievementType());
        dto.setAchievementName(achievement.getAchievementName());
        dto.setDescription(achievement.getDescription());
        dto.setEarnDate(achievement.getEarnDate());
        dto.setCreateTime(achievement.getCreateTime());
        dto.setUserName(achievement.getUserName());
        
        // 设置额外信息
        dto.setIconUrl(getAchievementIcon(achievement.getAchievementType()));
        dto.setIsUnlocked(true);
        dto.setProgress(100);
        
        return dto;
    }

    private String getAchievementIcon(String achievementType) {
        // 根据成就类型返回对应的图标URL
        switch (achievementType) {
            case "practice":
                return "/icons/achievements/practice.png";
            case "learning":
                return "/icons/achievements/learning.png";
            case "exam":
                return "/icons/achievements/exam.png";
            case "course":
                return "/icons/achievements/course.png";
            default:
                return "/icons/achievements/default.png";
        }
    }
} 